package pl.wroc.pwr.psi.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.Gson;

import pl.wroc.pwr.psi.entity.SlowoKluczowe;
import pl.wroc.pwr.psi.entity.Synonim;
import pl.wroc.pwr.psi.service.DefinicjaSynonimowService;
import pl.wroc.pwr.psi.service.SynonimService;
import pl.wroc.pwr.psi.service.SzablonService;

@Controller
public class DefinicjaSynonimowController {
	
	private static final String usunSKErrorMsg = "Nie moge usunac slowa kluczowego gdyz jest wykorzystywane w pytaniach otwartych.";

	@Autowired
	private DefinicjaSynonimowService definicjaSynonimowService;
	
	@Autowired
	private SynonimService synonimService;
	
	@Autowired
	private SzablonService szablonService;
	
	@RequestMapping("/szablony/*")
	public String showCreateTemplate(Model model) {
		model.addAttribute("szablons", szablonService.findAllSzablon());
		return "szablony";
	}
	
	@RequestMapping(value="/szablony/dodajsk", method=RequestMethod.POST)
	public String zdefiniujNoweSlowoKluczowe(@RequestParam String nazwa, @RequestParam(required=false) String[] synonimy, Model model) {

		System.out.println("Dodaje się sk " + nazwa);

		if (weryfikacjaSlowaKluczowego(nazwa)) {
			List<String> synonimyDoDodania = new ArrayList<String>();
			if(synonimy != null) {
				synonimyDoDodania.addAll(Arrays.asList(synonimy));
			}
			
			Integer newSlowoKluczowe = definicjaSynonimowService.utworzNoweSlowoKluczowe(nazwa, synonimyDoDodania);
			System.out.println("Dodano sk o id " + newSlowoKluczowe);
			model.addAttribute("errorMsg", false);
		} else {
			model.addAttribute("errorMsg", true);
			model.addAttribute("errorMsgText", nazwa);
		}
		
		return pokazSlowaKluczowe(model);
	}

	@RequestMapping("/szablony/usunsk")
	public @ResponseBody String usunSlowoKluczowe(@RequestParam Integer skId, Model model) {
		System.out.println("Usuwa sk: " + skId);
		try {
			definicjaSynonimowService.deleteSlowoKluczoweById(skId);
			
			if(potwierdzenieUsuniecia(skId)) {
				return "";
			} else {	
				return usunSKErrorMsg;
			}
			
		} catch (Exception e) {
			return usunSKErrorMsg;
		}
	}
	
	private boolean potwierdzenieUsuniecia(Integer skId) {
		SlowoKluczowe sk = definicjaSynonimowService.findSlowoKluczoweById(skId);
		return sk == null;
		
	}

	@RequestMapping("/szablony/edytujsk")
	public String edytujSlowoKluczowe(@RequestParam Integer skId, @RequestParam String nowaNazwa, Model model) {
		System.out.println("Zmienia nazwę sk: " + skId);
		definicjaSynonimowService.zmienNazweSlowoKluczowe(skId, nowaNazwa);
		return "redirect:" + "synonimy.html";
	}
	
	@RequestMapping("/szablony/usunsynonim")
	public @ResponseBody String usunSynonim(@RequestParam Integer synonimId) {
		System.out.println("Usuwam synonim: " + synonimId);
		synonimService.deleteSynonimById(synonimId);
		return "OK";
	}
	
	@RequestMapping("/szablony/synonimy")
	public String pokazSlowaKluczowe(Model model) {
		System.out.println("showSlowoKluszowes");
		Collection<SlowoKluczowe> slowoKluczowes = definicjaSynonimowService.findSlowaKluczowe();
		System.out.println("slowoKluczowes.size(): " + slowoKluczowes.size());
		
		ArrayList<SlowoKluczowe> slowaKluczowe = new ArrayList<SlowoKluczowe>(slowoKluczowes);
		Collections.sort(slowaKluczowe, getSlowoKluczoweComparator());
		
		model.addAttribute("slowakluczowe", slowaKluczowe);
		model.addAttribute("szablons", szablonService.findAllSzablon());
		return "synonimy";
	}

	private Comparator<SlowoKluczowe> getSlowoKluczoweComparator() {
		return new Comparator<SlowoKluczowe>(){

			@Override
			public int compare(SlowoKluczowe o1, SlowoKluczowe o2) {
				return o1.getNazwa().compareTo(o2.getNazwa());
			}

		};
	}
	
	@RequestMapping("/szablony/dodajsynonim")
	public @ResponseBody String addSynonim(@RequestParam Integer skId, @RequestParam String synonim) {
		
		System.out.println("Do sk o id " + skId + " dodano synonim " + synonim);
		
		SlowoKluczowe sk = definicjaSynonimowService.findSlowoKluczoweById(skId);
		
		Synonim newSynonim = new Synonim();
		newSynonim.setSynonim(synonim);
		newSynonim.setSlowoKluczowe(sk);
		
		Integer savedSynonimId = definicjaSynonimowService.saveSynonim(newSynonim);
		System.out.println("Dodano synonim o id " + savedSynonimId);
		
		
		Synonim synonimTO = new Synonim();
		synonimTO.setId(savedSynonimId);
		synonimTO.setSynonim(synonim);
		
		String synonimJson = new Gson().toJson(synonimTO);
		return synonimJson;
	}

	private boolean weryfikacjaSlowaKluczowego(String sk) {
		if (sk == null) {
			return false;
		}
		if (sk.trim().length() == 0) {
			return false;
		}
		if(definicjaSynonimowService.istniejeSlowoKluczowe(sk)) {
			return false;
		}		
		return true;
	}

}
